﻿// --------------------------------------------------------------------------------------------------------------------- 
// <copyright file="EulerExtensions.cs" company="Microsoft">
//   Copyright (c) Microsoft Corporation.  All rights reserved. THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
// </copyright>
// <summary>
//   Defines the EulerExtentions type.
// </summary>
// ---------------------------------------------------------------------------------------------------------------------
namespace EulerProblemsCSharp
{
    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.Linq;
    using Microsoft.FSharp.Math;

    /// <summary>
    /// Defines extension methods used for solving Project Euler problems.
    /// </summary>
    public static class EulerExtensions
    {
        /// <summary>
        /// Returns an enumeration of divisors for a given integer.
        /// </summary>
        /// <param name="value">
        /// The value.
        /// </param>
        /// <returns>
        /// Enumeration of divisors.
        /// </returns>
        public static IEnumerable<int> GetDivisors(this int value)
        {
            for (var i = (int)Math.Sqrt(value); i > 0; i--)
            {
                if (value % i == 0)
                {
                    yield return i;
                    yield return value / i;
                }
            }
        }

        /// <summary>
        /// Raised a BigInt to a given power using Fast Exponentiation.
        /// </summary>
        /// <param name="value">
        /// The value.
        /// </param>
        /// <param name="power">
        /// The power.
        /// </param>
        /// <returns>
        /// The value raised to a power.
        /// </returns>
        public static BigInt RaisedToThePowerOf(this BigInt value, int power)
        {
            if (power == 0)
            {
                return BigInt.One;
            }

            // recursive call
            var x = RaisedToThePowerOf(value, power / 2);

            if (power % 2 == 0)
            {
                return x * x;
            }
            
            return value * (x * x);
        }

        /// <summary>
        /// Determines whether a given integer is a palindrome
        /// </summary>
        /// <param name="value">
        /// The value.
        /// </param>
        /// <returns>
        /// True if the value is a palindrome.
        /// </returns>
        public static bool IsPalindrome(this int value)
        {
            return value.ToString(CultureInfo.InvariantCulture) == value.ToString(CultureInfo.InvariantCulture).ReverseString();
        }

        /// <summary>
        /// Determines whether a given integer is a palindrome in Base 2.
        /// </summary>
        /// <param name="value">The Value.</param>
        /// <returns>Trus is the value is a palindrome in Base 2.</returns>
        public static bool IsPalindromeInBase2(this int value)
        {
            return Convert.ToString(value, 2) == Convert.ToString(value, 2).ReverseString();
        }

        /// <summary>
        /// Reverses a string.
        /// </summary>
        /// <param name="value">String to reverse.</param>
        /// <returns>The reversed string.</returns>
        public static string ReverseString(this string value)
        {
            return new string(value.Reverse().ToArray());
        }
    }
}